package com.google.code.openperfmon.monapi.win;

import java.net.InetAddress;

import org.apache.log4j.Logger;

import com.google.code.openperfmon.monapi.Icmp;
import com.google.code.openperfmon.monapi.PingResult;

// based on net.azib.ipscan.core.net.WinIcmp
public class WinIcmp extends Icmp {
	private static Logger logger = Logger.getLogger(WinIcmp.class);
	
	private static native int icmpCreateFile();
	private static native int icmpSendEcho(int handle, byte[] address, byte[] pingData, byte[] replyData, int timeout);
	private static native void icmpCloseHandle(int handle);
	
	public WinIcmp() {
		
	}
	
	@Override
	public PingResult ping(InetAddress address, int count, int timeout) {
		
		byte[] pingData = new byte[56];
		byte[] replyData = new byte[56 + 100];
		
		int handle = icmpCreateFile();
		if (handle < 0) {
			logger.error("Unable to create Windows native ICMP handle.");
			return super.ping(address, count, timeout);
		}
			
		PingResult result = new PingResult();
		try {
			// send a bunch of packets
			for (int i = 1; i <= count && !Thread.currentThread().isInterrupted(); i++) {
				if (icmpSendEcho(handle, address.getAddress(), pingData, replyData, timeout) > 0) {
					int status = replyData[4] + (replyData[5]<<8) + (replyData[6]<<16) + (replyData[7]<<24);
					if (status == 0) {
						int roundTripTime = replyData[8] + (replyData[9]<<8) + (replyData[10]<<16) + (replyData[11]<<24); 
						int timeToLive = replyData[20] & 0xFF;
						result.addReply(roundTripTime);
						result.setTTL(timeToLive);
					}
				}
			}
		}
		finally {
			icmpCloseHandle(handle);
		}
								
		return result;
	}
}
